Implementation of the Code
List of Functions
- void initComm()
- void publishMessage(pub_topic, msg)
- String readMessage(sub_topic)
- void initIO()
- void initTimer()
- void startTimer()
- void clearLEDs()
Communication Initialization
The initComm()
function ensures that the AVR-IOT-Cellular-Mini board connects to the LTE network and the AWS MQTT broker as the first step in the application.
It also subscribes to the topic that the paired emoji cube sends messages.
void initComm() {
LedCtrl.begin();
LedCtrl.startupCycle();
Log.info("Starting initialization of MQTT Polling for AWS\r\n");
connectLTE();
connectMqtt();
}
Read Messages
The readMessage()
function checks if there are any messages available on the subscribed topic, which is passed as an argument.
On an incoming message, the newMessage()
sets a flag (new_message_flag) indicating that a new message has been received and copies the topic into char array topicBuffer
.
As readMessage()
is called when the new_message_flag is true, the topic is verified to match the topic in the topicBuffer.
It both prints the message received from the broker and returns the message as a string.
String readMessage(const char* sub_topic) {
String message;
if (mqttConnected) {
if (!strcmp(sub_topic, topicBuffer)){
message = MqttClient.readMessage(sub_topic);
if (message != "") {
Log.info("Got new message: ");
Log.info(message);
Log.info("\r\n");
}
return message;
}
else {
// MQTT is not connected. Need to re-establish connection
if (!lteConnected) {
// We're NOT connected to the LTE Network. Establish LTE connection first
connectLTE();
}
connectMqtt();
return "";
}
}
return "Error reading";
}
Send Messages
By passing the topic to send to and the message that is to be sent as arguments to the publishMessage()
function, the emojicube can publish it's messages to the MQTT broker.
void publishMessage(const char* pub_topic, const char* msg) {
if(mqttConnected) {
bool publishedSuccessfully = MqttClient.publish(pub_topic, msg);
if (!publishedSuccessfully) {
Log.error("Failed to publish\r\n");
}
}
else {
// MQTT is not connected. Need to re-establish connection
if (!lteConnected) {
// We're NOT connected to the LTE Network. Establish LTE connection first
connectLTE();
}
connectMqtt();
}
}
GPIO Initialization
The buttons act as inputs that trigger an interrupt and the LEDs are ouputs in the emojicube. The button and LED pins are configured accordingly.
void initIO() {
// Buttons setup : set as input,enable pull up, enable interrupts on level LOW
pinMode(BUTTON_1, INPUT);
pinMode(BUTTON_2, INPUT);
pinMode(BUTTON_3, INPUT);
PORTD.PIN1CTRL |= PORT_PULLUPEN_bm;
PORTD.PIN1CTRL |= PORT_ISC_LEVEL_gc;
PORTD.PIN3CTRL |= PORT_PULLUPEN_bm;
PORTD.PIN3CTRL |= PORT_ISC_LEVEL_gc;
PORTD.PIN4CTRL |= PORT_PULLUPEN_bm;
PORTD.PIN4CTRL |= PORT_ISC_LEVEL_gc;
// LEDs setup : set as output
pinMode(LED_Yellow, OUTPUT);
pinMode(LED_Green, OUTPUT);
pinMode(LED_Red, OUTPUT);
clearLEDs();
}
Timer
Initialization
The timer/counter peripheral TCB0 is used in this demo to control how long a specific emoji (LED) should be turned ON for an incoming message. According to the example configurations, the timer overflow flag is set every 3ms and the period is determined by counting the number of times the flag is set in the timer ISR (for eg., if the flag is set 10 times, 30 ms has passed).
void initTimer() {
// Set capture value to achieve 3 ms period
TCB0.CCMP = 0xEA5F;
// Enable timer overflow interrupt
TCB0.INTCTRL = 0x01;
// Select PIT mode for TCB0 (default)
TCB0.CTRLB = 0x00;
// Disable timer
TCB0.CTRLA = 0x00;
}
Starting the timer
The startTimer()
function is called after a specificemoji/LED is turned ON. When the timerflag value changes to 'true', it indicates that the timeout value has expired and the LED can be turned OFF again.
void startTimer() {
clearLEDs();
TCB0.CTRLA = 0x00;
timerFlag = false;
timerCount = 0;
TCB0.INTFLAGS = 0x01;
TCB0.CTRLA = 0x03;
}
Clear LEDs
This simple function comes in handy to clear or turn OFF all the LEDs at once.
void clearLEDs() {
analogWrite(LED_Yellow, 0);
analogWrite(LED_Red, 0);
analogWrite (LED_Green, 0);
}